package cn.com.nes.site.service.product.impl;

import cn.com.nes.common.exception.MissBusinessParameterException;
import cn.com.nes.common.util.CopyUtils;
import cn.com.nes.mybatis.agent.ope.entity.ProductSeriesAndEnergy;
import cn.com.nes.mybatis.agent.ope.mapper.ProductSeriesAndEnergyMapper;
import cn.com.nes.mybatis.agent.system.entity.TParam;
import cn.com.nes.site.entity.PageData;
import cn.com.nes.site.entity.dto.product.ProductSeriesAndEnergyDTO;
import cn.com.nes.site.entity.em.product.ProductAttributeEnum;
import cn.com.nes.site.entity.vo.product.DelProductSeriesAndEnergyVO;
import cn.com.nes.site.entity.vo.product.QueryProductSeriesAndEnergyPageVO;
import cn.com.nes.site.entity.vo.product.SaveProductSeriesAndEnergyVO;
import cn.com.nes.site.modules.agent.grant.AgentGrant;
import cn.com.nes.site.service.product.ProductAttributeHandlerFactory;
import cn.com.nes.site.service.product.ProductSeriesAndEnergyService;
import cn.com.nes.site.service.product.bo.QueryProductSeriesAndEnergyBO;
import cn.com.nes.site.service.product.handle.ProductAttributeHandler;
import cn.com.nes.site.service.system.dict.TParamService;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 能源分类、品牌系列Service
 *
 * @Author: ShenWei
 * @Date: 2024/03/26/16:16
 */
@Service
public class ProductSeriesAndEnergyServiceImpl extends ServiceImpl<ProductSeriesAndEnergyMapper, ProductSeriesAndEnergy> implements ProductSeriesAndEnergyService {

    @Resource
    private ProductSeriesAndEnergyMapper productSeriesAndEnergyMapper;

    @Resource
    private TParamService tParamService;

    @Resource
    private ProductAttributeHandlerFactory productAttributeHandlerFactory;

    @Resource
    private AgentGrant agentGrant;

    private Map<String, String> energyTypeMap = new HashMap<>();

    public static final Long PRODUCT_ENERGY_ROOT_NODE_ID = 0L; // parentId=0L - 表示节点为根节点
    public static final Long PRODUCT_SERIES_ROOT_NODE_ID = 1L; // parentId=1L - 创今公司品牌名称

    @Override
    public PageData saveProductSeriesAndEnergy(SaveProductSeriesAndEnergyVO vo) {
        ProductAttributeHandler productAttributeHandler = productAttributeHandlerFactory.getProductAttributeHandler(vo.getNodeType());

        Long id;
        if (ObjectUtil.isNull(vo.getId())) {
            id = productAttributeHandler.addNode(vo);
        } else {
            id = productAttributeHandler.updateNode(vo);
        }
        PageData pageData = PageData.ok();
        pageData.setKey(id.toString());
        return pageData;
    }

    @Override
    public PageData delProductSeriesAndEnergy(DelProductSeriesAndEnergyVO vo) {
        if (ObjectUtil.isNull(vo.getId())) {
            throw new MissBusinessParameterException("id");
        }

        Long userId = Long.valueOf(vo.getUserInfo().getId());

        ProductSeriesAndEnergy productSeriesAndEnergy = new ProductSeriesAndEnergy();
        productSeriesAndEnergy.setId(vo.getId());
        productSeriesAndEnergy.setDeleted(true);
        productSeriesAndEnergy.setGmtModified(new Date());
        productSeriesAndEnergy.setGmtModifiedId(userId);

        productSeriesAndEnergyMapper.updateById(productSeriesAndEnergy);
        return PageData.ok("删除成功");
    }

    @Override
    public PageData getProductSeriesAndEnergyTree(QueryProductSeriesAndEnergyPageVO vo) throws Exception {
        Integer nodeType = vo.getNodeType();
        Boolean enable = vo.getEnable();
        List<ProductSeriesAndEnergyDTO> list = new ArrayList<>();
        // 区分查询品牌还是能源分类,品牌按公司查,能源分类查询全部
        String companyId = StrUtil.EMPTY;
        if (ObjectUtil.isNotNull(nodeType) && ProductAttributeEnum.BRAND.getKey().equals(nodeType)) {
            companyId = vo.getOperateUserCompanyId();
        }

        // 查询能源分类字典，方便使用
        List<TParam> energyTypeList = tParamService.getList("323");
        if (CollectionUtil.isNotEmpty(energyTypeList)) {
            for (TParam energyType : energyTypeList) {
                energyTypeMap.put(energyType.getValue(), energyType.getName());
            }
        }

        if (CollectionUtil.isEmpty(vo.getEnergyTypeList()) && CollectionUtil.isEmpty(vo.getProductEnergyIdList())) {
            // 从上到下构造树
            list = productSeriesAndEnergyMapper.getParentNode(nodeType, companyId, enable);
            for (ProductSeriesAndEnergyDTO dto : list) {
                List<ProductSeriesAndEnergyDTO> childList = getChildList(dto.getId(), enable, new ArrayList<>());
                dto.setChildList(childList);
                handleEnergyTypeData(dto);
            }
            // 查询授权来的全部产品的品牌
            if (ObjectUtil.isNotNull(nodeType) && ProductAttributeEnum.BRAND.getKey().equals(nodeType)) {
                List<Long> grantBrandNodeIdList = agentGrant.getGrantBrandNode(companyId);
                if (CollectionUtil.isNotEmpty(grantBrandNodeIdList)) {
                    List<ProductSeriesAndEnergyDTO> detailByIdList = this.getProductSeriesAndEnergyListByIdList(grantBrandNodeIdList);
                    if (CollectionUtil.isNotEmpty(detailByIdList)) {
                        list.addAll(detailByIdList);
                        list = convertToTree(list);
                    }
                }
            }
        } else {
            // 从下到上构造树
            // 组装参数
            QueryProductSeriesAndEnergyBO queryBO = vo.convertToBo(QueryProductSeriesAndEnergyBO.class);
            queryBO.setCompanyId(companyId);

            list = productSeriesAndEnergyMapper.queryEnergyNodeList(queryBO);
            if (ProductAttributeEnum.BRAND.getKey().equals(nodeType)) {
                // 如果入参指定了能源分类的id，说明是用户想通过能源分类查询品牌系列，所以直接查询品牌系列即可
                queryBO.setProductEnergyIdList(handleEnergyIdList(list, vo.getProductEnergyIdList()));
                list = queryBrandDataList(queryBO);
            }
            list = convertToTree(list);
        }
        Page<ProductSeriesAndEnergyDTO> page = new Page<>(1, 1);
        return PageData.ok(page, list);
    }

    @Override
    public List<Long> getAllChildIds(Long parentId, Boolean enable) {
        List<Long> childIdList = new ArrayList<>();

        if (Objects.isNull(parentId)) {
            return childIdList;
        }
        childIdList.add(parentId);
        getChildList(parentId, enable, childIdList);

        return childIdList;
    }

    @Override
    public ProductSeriesAndEnergyDTO getDetailById(Long id) {
        ProductSeriesAndEnergyDTO dto = new ProductSeriesAndEnergyDTO();

        QueryWrapper<ProductSeriesAndEnergy> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        ProductSeriesAndEnergy productSeriesAndEnergy = this.getOne(wrapper);

        if (Objects.isNull(productSeriesAndEnergy)) {
            return dto;
        }
        BeanUtils.copyProperties(productSeriesAndEnergy, dto);
        handleEnergyTypeData(dto);

        return dto;
    }

    @Override
    public List<ProductSeriesAndEnergyDTO> getProductSeriesAndEnergyListByIdList(List<Long> idList) {
        List<ProductSeriesAndEnergyDTO> record = new ArrayList<>();

        QueryWrapper<ProductSeriesAndEnergy> wrapper = new QueryWrapper<>();
        wrapper.in("id", idList);
        List<ProductSeriesAndEnergy> productSeriesAndEnergies = this.baseMapper.selectList(wrapper);

        if (CollectionUtil.isEmpty(productSeriesAndEnergies)) {
            return record;
        }
        return CopyUtils.copyList(productSeriesAndEnergies, ProductSeriesAndEnergyDTO.class);
    }

    @Override
    public List<Long> getEnergyIds(String nodeName, String companyId) {
        List<Long> idList = new ArrayList<>();

        QueryWrapper<ProductSeriesAndEnergy> wrapper = new QueryWrapper<>();
        wrapper.eq("company_id", companyId);
        wrapper.like("node_name", nodeName);

        List<ProductSeriesAndEnergy> productSeriesAndEnergies = this.list(wrapper);
        if (CollectionUtil.isNotEmpty(productSeriesAndEnergies)) {
            idList = productSeriesAndEnergies.stream().map(ProductSeriesAndEnergy::getId).collect(Collectors.toList());
        }

        return idList;
    }

    @Override
    public List<Map<String, String>> getSeriesConfigTemplate() {
        List<ProductSeriesAndEnergyDTO> list = this.baseMapper.getSeriesList();

        List<Map<String, String>> configTemplate = new ArrayList<>();
        if (CollectionUtil.isEmpty(list)) {
            return configTemplate;
        }
        for (ProductSeriesAndEnergyDTO item : list) {
            Map<String, String> map = new HashMap<>();
            map.put("value", String.valueOf(item.getId()));
            map.put("name", item.getNodeName());
            configTemplate.add(map);
        }
        return configTemplate;
    }

    @Override
    public List<ProductSeriesAndEnergyDTO> getEnergyClassification(QueryProductSeriesAndEnergyBO queryBO) {
        return productSeriesAndEnergyMapper.queryEnergyNodeList(queryBO);
    }

    // 递归方法 - 递归查询子节点
    private List<ProductSeriesAndEnergyDTO> getChildList(Long parentId, Boolean enable, List<Long> childIdList) {
        List<ProductSeriesAndEnergyDTO> childList = productSeriesAndEnergyMapper.getChildListByParentId(parentId, enable);

        for (ProductSeriesAndEnergyDTO energyDTO : childList) {
            List<ProductSeriesAndEnergyDTO> list = getChildList(energyDTO.getId(), enable, childIdList);
            energyDTO.setChildList(list);
            handleEnergyTypeData(energyDTO);
            childIdList.add(energyDTO.getId()); // 专门用来存储所有子节点的id
        }
        return childList;
    }

    // 查询品牌系列列表
    public List<ProductSeriesAndEnergyDTO> queryBrandDataList(QueryProductSeriesAndEnergyBO queryBO) {
        if (CollectionUtil.isEmpty(queryBO.getProductEnergyIdList())) {
            return Collections.emptyList();
        }
        return productSeriesAndEnergyMapper.querySeriesNodeList(queryBO);
    }

    // list转树
    private List<ProductSeriesAndEnergyDTO> convertToTree(List<ProductSeriesAndEnergyDTO> sourceList) {
        if (CollectionUtil.isEmpty(sourceList)) {
            return sourceList;
        }
        // 确定树结构有几层
        Integer maxLevel = sourceList.stream().map(ProductSeriesAndEnergyDTO::getLevel).max(Integer::compareTo).get();
        // 递归补全全部上级节点
        if (maxLevel > 0) {
            Set<Long> parentIdList = sourceList.stream().filter(n -> maxLevel.equals(n.getLevel())).map(ProductSeriesAndEnergyDTO::getParentId).collect(Collectors.toSet());
            findParentNodeData(sourceList, maxLevel, parentIdList);
        }


        // 转换为树结构
        // 节点字典，用于快速查找节点,顺带去重
        Map<Long, ProductSeriesAndEnergyDTO> nodeMap = new HashMap<>();
        // 将所有节点存储到字典中
        for (ProductSeriesAndEnergyDTO node : sourceList) {
            if (PRODUCT_SERIES_ROOT_NODE_ID.equals(node.getId())) {
                continue;
            }
            node.setChildList(new ArrayList<>());
            handleEnergyTypeData(node);
            nodeMap.put(node.getId(), node);
        }
        // 建立父子关系
        List<ProductSeriesAndEnergyDTO> rootNodeList = new ArrayList<>();
        for (ProductSeriesAndEnergyDTO node : nodeMap.values()) {
            if (PRODUCT_SERIES_ROOT_NODE_ID.equals(node.getParentId()) || PRODUCT_ENERGY_ROOT_NODE_ID.equals(node.getParentId())) {
                // 根节点，没有父节点
                rootNodeList.add(node);
            } else {
                // 根据 parentId 将节点添加到其父节点的 children 列表中
                ProductSeriesAndEnergyDTO parent = nodeMap.get(node.getParentId());
                if (parent != null) {
                    parent.getChildList().add(node);
                }
            }
        }
        return rootNodeList;
    }

    // 获取父级节点
    private void findParentNodeData(List<ProductSeriesAndEnergyDTO> sourceList, Integer level, Set<Long> parentIdList) {
        if (CollectionUtil.isEmpty(parentIdList)) {
            return;
        }
        sourceList.addAll(productSeriesAndEnergyMapper.getNodeListById(parentIdList));
        if (level == 0) {
            return;
        }
        findParentNodeData(sourceList, level - 1, sourceList.stream().filter(n -> n.getLevel().equals(level - 1)).map(ProductSeriesAndEnergyDTO::getParentId).collect(Collectors.toSet()));
    }

    // 处理能源分类信息
    private void handleEnergyTypeData(ProductSeriesAndEnergyDTO dto) {
        if (StrUtil.isNotBlank(dto.getEnergyType())) {
            dto.setEnergyTypeList(new ArrayList<>());
            for (String s : dto.getEnergyType().split(",")) {
                Map<String, String> map = new HashMap<>();
                map.put("value", s);
                map.put("name", energyTypeMap.get(s));
                dto.getEnergyTypeList().add(map);
            }
        }
    }

    // 处理能源分类的id列表 - 取出指定的节点id及其下级的节点id
    @Override
    public Set<Long> handleEnergyIdList(List<ProductSeriesAndEnergyDTO> sourceList, Set<Long> productEnergyIdList) {
        if (CollectionUtil.isEmpty(sourceList)) {
            return new HashSet<>();
        }
        if (CollectionUtil.isEmpty(productEnergyIdList)) {
            return sourceList.stream().map(ProductSeriesAndEnergyDTO::getId).collect(Collectors.toSet());
        }

        // 确定树结构有几层
        Integer maxLevel = sourceList.stream().map(ProductSeriesAndEnergyDTO::getLevel).max(Integer::compareTo).get();

        // 递归补全树结构的全部节点
        if (maxLevel > 0) {
            Set<Long> parentIdList = sourceList.stream().filter(n -> maxLevel.equals(n.getLevel())).map(ProductSeriesAndEnergyDTO::getParentId).collect(Collectors.toSet());
            findParentNodeData(sourceList, maxLevel, parentIdList);
        }

        // 准备一个容器收集结果 - 先收集指定的节点id
        Set<Long> result = sourceList.stream().map(ProductSeriesAndEnergyDTO::getId).filter(productEnergyIdList::contains).collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(result)) {
            return new HashSet<>();
        }

        // 收集result中每个节点的子节点
        for (int level = 0; level <= maxLevel; level++) {
            result.addAll(sourceList.stream()
                    .filter(n -> result.contains(n.getParentId()))
                    .map(ProductSeriesAndEnergyDTO::getId)
                    .collect(Collectors.toList())
            );
        }
        return result;
    }

    @Override
    public ProductSeriesAndEnergy getIdByNodeName(String name) {
        LambdaQueryWrapper<ProductSeriesAndEnergy> queryWrapper=new LambdaQueryWrapper();
        queryWrapper.eq(ProductSeriesAndEnergy::getNodeName,name);
        queryWrapper.eq(ProductSeriesAndEnergy::getNodeType,1);
        return  productSeriesAndEnergyMapper.selectOne(queryWrapper);
    }

    @Override
    public ProductSeriesAndEnergy getbrandIdByBrandName(String brandName, String companyId) {
        LambdaQueryWrapper<ProductSeriesAndEnergy> queryWrapper=new LambdaQueryWrapper();
        queryWrapper.eq(ProductSeriesAndEnergy::getNodeName,brandName);
        queryWrapper.eq(ProductSeriesAndEnergy::getCompanyId,companyId);
        queryWrapper.eq(ProductSeriesAndEnergy::getNodeType,0);
        return  productSeriesAndEnergyMapper.selectOne(queryWrapper);
    }

}
